home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / dkbtrace / pbmplus / source / libtiff / tif_pack.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-21  |  5.6 KB  |  226 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: /usr/people/sam/tiff/libtiff/RCS/tif_packbits.c,v 1.20 91/08/21 17:11:06 sam Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1988, 1989, 1990, 1991 Sam Leffler
  7.  * Copyright (c) 1991 Silicon Graphics, Inc.
  8.  *
  9.  * Permission to use, copy, modify, distribute, and sell this software and 
  10.  * its documentation for any purpose is hereby granted without fee, provided
  11.  * that (i) the above copyright notices and this permission notice appear in
  12.  * all copies of the software and related documentation, and (ii) the names of
  13.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  14.  * publicity relating to the software without the specific, prior written
  15.  * permission of Sam Leffler and Silicon Graphics.
  16.  * 
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  18.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  19.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  20.  * 
  21.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  22.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  23.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  24.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  25.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  26.  * OF THIS SOFTWARE.
  27.  */
  28.  
  29. /*
  30.  * TIFF Library.
  31.  *
  32.  * PackBits Compression Algorithm Support
  33.  */
  34. #include "tiffioP.h"
  35.  
  36. #if USE_PROTOTYPES
  37. static    int PackBitsEncode(TIFF *, u_char *, int, u_int);
  38. static    int PackBitsDecode(TIFF *, u_char *, int, u_int);
  39. #else
  40. static    int PackBitsEncode(), PackBitsDecode();
  41. #endif
  42.  
  43. TIFFInitPackBits(tif)
  44.     TIFF *tif;
  45. {
  46.     tif->tif_decoderow = PackBitsDecode;
  47.     tif->tif_decodestrip = PackBitsDecode;
  48.     tif->tif_decodetile = PackBitsDecode;
  49.     tif->tif_encoderow = PackBitsEncode;
  50.     tif->tif_encodestrip = PackBitsEncode;
  51.     tif->tif_encodetile = PackBitsEncode;
  52.     return (1);
  53. }
  54.  
  55. /*
  56.  * Encode a scanline of pixels.
  57.  */
  58. static int
  59. PackBitsEncode(tif, bp, cc, s)
  60.     TIFF *tif;
  61.     u_char *bp;
  62.     register int cc;
  63.     u_int s;
  64. {
  65.     register char *op, *lastliteral;
  66.     register int n, b;
  67.     enum { BASE, LITERAL, RUN, LITERAL_RUN } state;
  68.     char *ep;
  69.     int slop;
  70.  
  71.     op = tif->tif_rawcp;
  72.     ep = tif->tif_rawdata + tif->tif_rawdatasize;
  73.     state = BASE;
  74.     lastliteral = 0;
  75.     while (cc > 0) {
  76.         /*
  77.          * Find the longest string of identical bytes.
  78.          */
  79.         b = *bp++, cc--, n = 1;
  80.         for (; cc > 0 && b == *bp; cc--, bp++)
  81.             n++;
  82.     again:
  83.         if (op + 2 >= ep) {        /* insure space for new data */
  84.             /*
  85.              * Be careful about writing the last
  86.              * literal.  Must write up to that point
  87.              * and then copy the remainder to the
  88.              * front of the buffer.
  89.              */
  90.             if (state == LITERAL || state == LITERAL_RUN) {
  91.                 slop = op - lastliteral;
  92.                 tif->tif_rawcc += lastliteral - tif->tif_rawcp;
  93.                 if (!TIFFFlushData1(tif))
  94.                     return (-1);
  95.                 op = tif->tif_rawcp;
  96.                 for (; slop-- > 0; *op++ = *lastliteral++)
  97.                     ;
  98.                 lastliteral = tif->tif_rawcp;
  99.             } else {
  100.                 tif->tif_rawcc += op - tif->tif_rawcp;
  101.                 if (!TIFFFlushData1(tif))
  102.                     return (-1);
  103.                 op = tif->tif_rawcp;
  104.             }
  105.         }
  106.         switch (state) {
  107.         case BASE:        /* initial state, set run/literal */
  108.             if (n > 1) {
  109.                 state = RUN;
  110.                 if (n > 128) {
  111.                     *op++ = -127;
  112.                     *op++ = b;
  113.                     n -= 128;
  114.                     goto again;
  115.                 }
  116.                 *op++ = -(n-1);
  117.                 *op++ = b;
  118.             } else {
  119.                 lastliteral = op;
  120.                 *op++ = 0;
  121.                 *op++ = b;
  122.                 state = LITERAL;
  123.             }
  124.             break;
  125.         case LITERAL:        /* last object was literal string */
  126.             if (n > 1) {
  127.                 state = LITERAL_RUN;
  128.                 if (n > 128) {
  129.                     *op++ = -127;
  130.                     *op++ = b;
  131.                     n -= 128;
  132.                     goto again;
  133.                 }
  134.                 *op++ = -(n-1);        /* encode run */
  135.                 *op++ = b;
  136.             } else {            /* extend literal */
  137.                 if (++(*lastliteral) == 127)
  138.                     state = BASE;
  139.                 *op++ = b;
  140.             }
  141.             break;
  142.         case RUN:        /* last object was run */
  143.             if (n > 1) {
  144.                 if (n > 128) {
  145.                     *op++ = -127;
  146.                     *op++ = b;
  147.                     n -= 128;
  148.                     goto again;
  149.                 }
  150.                 *op++ = -(n-1);
  151.                 *op++ = b;
  152.             } else {
  153.                 lastliteral = op;
  154.                 *op++ = 0;
  155.                 *op++ = b;
  156.                 state = LITERAL;
  157.             }
  158.             break;
  159.         case LITERAL_RUN:    /* literal followed by a run */
  160.             /*
  161.              * Check to see if previous run should
  162.              * be converted to a literal, in which
  163.              * case we convert literal-run-literal
  164.              * to a single literal.
  165.              */
  166.             if (n == 1 && op[-2] == (char)-1 &&
  167.                 *lastliteral < 126) {
  168.                 state = (((*lastliteral) += 2) == 127 ?
  169.                     BASE : LITERAL);
  170.                 op[-2] = op[-1];    /* replicate */
  171.             } else
  172.                 state = RUN;
  173.             goto again;
  174.         }
  175.     }
  176.     tif->tif_rawcc += op - tif->tif_rawcp;
  177.     tif->tif_rawcp = op;
  178.     return (1);
  179. }
  180.  
  181. static int
  182. PackBitsDecode(tif, op, occ, s)
  183.     TIFF *tif;
  184.     register u_char *op;
  185.     register int occ;
  186.     u_int s;
  187. {
  188.     register char *bp;
  189.     register int n, b;
  190.     register int cc;
  191.  
  192.     bp = tif->tif_rawcp; cc = tif->tif_rawcc;
  193.     while (cc > 0 && occ > 0) {
  194.         n = (int) *bp++;
  195.         /*
  196.          * Watch out for compilers that
  197.          * don't sign extend chars...
  198.          */
  199.         if (n >= 128)
  200.             n -= 256;
  201.         if (n < 0) {        /* replicate next byte -n+1 times */
  202.             cc--;
  203.             if (n == -128)    /* nop */
  204.                 continue;
  205.             n = -n + 1;
  206.             occ -= n;
  207.             for (b = *bp++; n-- > 0;)
  208.                 *op++ = b;
  209.         } else {        /* copy next n+1 bytes literally */
  210.             bcopy(bp, op, ++n);
  211.             op += n; occ -= n;
  212.             bp += n; cc -= n;
  213.         }
  214.     }
  215.     tif->tif_rawcp = bp;
  216.     tif->tif_rawcc = cc;
  217.     if (occ > 0) {
  218.         TIFFError(tif->tif_name,
  219.             "PackBitsDecode: Not enough data for scanline %d",
  220.             tif->tif_row);
  221.         return (0);
  222.     }
  223.     /* check for buffer overruns? */
  224.     return (1);
  225. }
  226.